﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Projekt.Cameras
{
    public class FreeCamera : BaseCamera
    {
        public float Yaw { get; set; }
        public float Pitch { get; set; }

        public Vector3 Target { get; private set; }

        private Vector3 translation;

        // amount that the camera should turn
        private float deltaX = 0;
        private float deltaY = 0;

        MouseState lastMouseState;

        public FreeCamera(Vector3 Position, float Yaw, float Pitch, GraphicsDevice graphicsDevice)
            : base(graphicsDevice)
        {
            this.Position = Position;
            this.Yaw = Yaw;
            this.Pitch = Pitch;

            Mouse.SetPosition(GraphicsDevice.PresentationParameters.BackBufferWidth / 2, GraphicsDevice.PresentationParameters.BackBufferHeight / 2);
            translation = Vector3.Zero;

            lastMouseState = Mouse.GetState();
        }

        public void Rotate(float YawChange, float PitchChange)
        {
            this.Yaw += YawChange;
            this.Pitch += PitchChange;
        }

        public void Move(Vector3 Translation)
        {
            this.translation += Translation;
        }

        public void Fly(GameTime gameTime)
        {
            //Get the new keyboard and mouse state
            MouseState mouseState = Mouse.GetState();
            Mouse.SetPosition(GraphicsDevice.PresentationParameters.BackBufferWidth / 2, GraphicsDevice.PresentationParameters.BackBufferHeight / 2);
            KeyboardState keyState = Keyboard.GetState();

            //Determine how much the camera should turn
            deltaX += (float)lastMouseState.X - (float)mouseState.X;
            deltaY += (float)lastMouseState.Y - (float)mouseState.Y;

            //Rotete the camera
            this.Rotate(deltaX * .005f, deltaY * .005f);

            ////Calculate scroll whell movement
            //float scrollDelta = (float)lastMouseState.ScrollWheelValue - (float)mouseState.ScrollWheelValue;

            Vector3 translation = Vector3.Zero;

            //Determine in which direction to move the camera
            if (keyState.IsKeyDown(Keys.W)) translation += Vector3.Forward;
            if (keyState.IsKeyDown(Keys.S)) translation += Vector3.Backward;
            if (keyState.IsKeyDown(Keys.A)) translation += Vector3.Left;
            if (keyState.IsKeyDown(Keys.D)) translation += Vector3.Right;
            if (keyState.IsKeyDown(Keys.Space)) translation += Vector3.Up;
            if (keyState.IsKeyDown(Keys.LeftControl)) translation += Vector3.Down;

            //Move 3 units per millisecond, independent of frame rate
            translation *= 1.2f * (float)gameTime.ElapsedGameTime.TotalMilliseconds;

            //Move the camera
            this.Move(translation);

            //Update the camera
            //this.Update();

            //Update the mouse state
            lastMouseState = mouseState;
        }

        public override void Update()
        {
            //Calculate the rotation matrix
            Matrix rotation = Matrix.CreateFromYawPitchRoll(Yaw, Pitch, 0);

            //Offset the position and reset the translation
            translation = Vector3.Transform(translation, rotation);
            Position += translation;
            translation = Vector3.Zero;

            //Calculate the new target
            Vector3 forward = Vector3.Transform(Vector3.Forward, rotation);
            Target = Position + forward;

            //Calculate the up vector
            Vector3 up = Vector3.Transform(Vector3.Up, rotation);

            //Calculate the view matrix
            View = Matrix.CreateLookAt(Position, Target, up);
        }
    }
}
